﻿using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace Simulator
{
	static class Program
	{
		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main ()
		{
			Application.EnableVisualStyles ();
			Application.SetCompatibleTextRenderingDefault (false);
			Application.AddMessageFilter (new MouseWheelMessageFilter ());
			Application.Run (new Form1 ());
		}
	}

	/// <summary>
	/// Ensures that all mouse wheel messages are dispatched to the
	/// window under the cursor, rather than the window with input
	/// focus.
	/// </summary>
	public class MouseWheelMessageFilter : IMessageFilter
	{
		[StructLayout (LayoutKind.Sequential)]
		private struct POINT
		{
			public int x;
			public int y;
		}

		[DllImport ("user32.dll")]
		private static extern IntPtr WindowFromPoint ([In] MouseWheelMessageFilter.POINT point);

		[DllImport ("user32.dll")]
		public static extern int SendMessage (IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

		private const int WM_MOUSEWHEEL = 0x020A;

		public bool PreFilterMessage (ref Message m)
		{
			if (m.Msg == WM_MOUSEWHEEL)
			{
				int screenX = (int) (short) (ushort) m.LParam.ToInt32 ();
				int screenY = (int) (short) (ushort) (m.LParam.ToInt32 () >> 16);

				MouseWheelMessageFilter.POINT point = new MouseWheelMessageFilter.POINT ();
				point.x = (int) screenX;
				point.y = (int) screenY;

				IntPtr hWnd = MouseWheelMessageFilter.WindowFromPoint (point);
				if (hWnd != IntPtr.Zero)
				{
					MouseWheelMessageFilter.SendMessage (hWnd, (uint) m.Msg, m.WParam, m.LParam);
				}

				return true; // stop this message being dispatched
			}

			return false;
		}
	}
}